package com.wangsd.web.coupon.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wangsd.common.exception.BusinessException;
import com.wangsd.common.utils.DateUtils;
import com.wangsd.common.utils.HttpUtil;
import com.wangsd.web.coupon.entity.*;
import com.wangsd.web.coupon.mapper.BusinessCouponMapper;
import com.wangsd.web.coupon.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivateKey;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author generator
 * @since 2020-01-07
 */
@Service
@Slf4j
public class BusinessCouponServiceImpl extends ServiceImpl<BusinessCouponMapper, BusinessCoupon> implements BusinessCouponService {

    @Resource
    BusinessCouponMapper businessCouponMapper;

    @Autowired
    ServiceBusinessService serviceBusinessService;
    @Autowired
    CompanyService companyService;
    @Autowired
    MemberCouponService memberCouponService;
    @Autowired
    MerchantService merchantService;
    @Autowired
    TOrderService orderService;

    private CloseableHttpClient httpClient;

    private AutoUpdateCertificatesVerifier verifier;

    private static final String createCouponUrl = "https://api.mch.weixin.qq.com/v3/marketing/busifavor/stocks";

    private static final String useCouponUrl = "https://api.mch.weixin.qq.com/v3/marketing/busifavor/coupons/use";

    private void beforeMake(ServiceBusiness entity) throws Exception {
        String privateKey = entity.getPrivateKey();
        String mchId = entity.getMchId();
        String mchSerialNo = entity.getMchSerialNo();
        String apiV3Key = entity.getApiV3Key();
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
                new ByteArrayInputStream(privateKey.getBytes("utf-8")));

        //使用自动更新的签名验证器，不需要传入证书
        verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),
                apiV3Key.getBytes("utf-8"));

        httpClient = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier))
                .build();
    }

    @Override
    @Transactional
    public void add(BusinessCoupon entity) throws BusinessException, IOException {
        Company company = companyService.getById(entity.getCompanyId());
        if (company == null) {
            throw new BusinessException(4000, "该商圈不存在");
        }
        ServiceBusiness serviceBusiness = serviceBusinessService.selectBusinessByCode(company.getCode());
        if (serviceBusiness == null) {
            throw new BusinessException(4000, "该服务商不存在");
        }

        String outRequestNo = serviceBusiness.getMchId() + System.currentTimeMillis();
        /*调用微信商家券创建接口*/
        JSONObject baseParams = new JSONObject();
        baseParams.put("stock_name", entity.getStockName());
        baseParams.put("belong_merchant", entity.getBelongMerchant());
        baseParams.put("goods_name", entity.getGoodsName());
        baseParams.put("stock_type", entity.getStockType());
        baseParams.put("coupon_use_rule", entity.getCouponUseRule());
        baseParams.put("stock_send_rule", entity.getStockSendRule());
        baseParams.put("out_request_no", outRequestNo);
        baseParams.put("coupon_code_mode", entity.getCouponCodeMode());
        /*保存基础数据*/

        try {
            beforeMake(serviceBusiness);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(4002, "服务商参数配置异常");
        }
        /*调用微信创建商家券接口*/
        HttpPost httpPost = new HttpPost(createCouponUrl);
        InputStream stream = new ByteArrayInputStream(JSON.toJSONString(baseParams).getBytes("utf-8"));
        InputStreamEntity reqEntity = new InputStreamEntity(stream);
        reqEntity.setContentType("application/json");
        httpPost.setEntity(reqEntity);
        httpPost.addHeader("Accept", "application/json");
        log.info(JSON.toJSONString(baseParams));
        CloseableHttpResponse response = httpClient.execute(httpPost);
        String result = HttpUtil.handleResponse(createCouponUrl, "UTF-8", response);
        log.info("创建商家券接口响应数据：" + result);
        if (result != null) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("PARAM_ERROR")) {
                throw new BusinessException(4001, result);
            }

            String stockId = jsonObject.getString("stock_id");
            entity.setStockId(stockId);
        } else {
            throw new BusinessException(4001, "创建商家券接口响应数据异常");
        }
        entity.setAvailableBeginTime(DateUtils.getDiffZone(entity.getAvailableBeginTime()));
        entity.setAvailableEndTime(DateUtils.getDiffZone(entity.getAvailableEndTime()));
        entity.setOutRequestNo(outRequestNo);
        entity.setUsableBusinessCouponCount(entity.getMaxCoupons());
        businessCouponMapper.insert(entity);
    }

    @Override
    public IPage<BusinessCoupon> selectPage(String code, Integer pageNum, Integer pageSize, BusinessCoupon businessCoupon) {
        Page<BusinessCoupon> page = new Page<>(pageNum, pageSize);
        IPage<BusinessCoupon> couponIPage = businessCouponMapper.selectListXml(page, code, businessCoupon);
        return couponIPage;
    }

    @Override
    public BusinessCoupon selectRepeat(String stockName, Long id) {
        QueryWrapper<BusinessCoupon> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stock_name", stockName);
        if (id != null) {
            queryWrapper.ne("id", id);
        }
        return businessCouponMapper.selectOne(queryWrapper);
    }

    @Override
    @Transactional
    public void useBusinessCoupon(String couponCode, String storeCode) throws BusinessException, IOException {
        ServiceBusiness serviceBusiness = serviceBusinessService.selectBusinessByCode(storeCode);
        if (serviceBusiness == null) {
            throw new BusinessException(4000, "该服务商不存在");
        }
        /*保存基础数据*/
        try {
            beforeMake(serviceBusiness);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(4002, "服务商参数配置异常");
        }
        MemberCoupon memberCoupon = memberCouponService.getOne(new QueryWrapper<MemberCoupon>().eq("coupon_code", couponCode));
        String outRequestNo = serviceBusiness.getMchId() + System.currentTimeMillis();

        BusinessCoupon businessCoupon = businessCouponMapper.selectOne(new QueryWrapper<BusinessCoupon>().eq("stock_id", memberCoupon.getStockId()));
        if (businessCoupon != null) {
            String[] split = storeCode.split("-");
            String merchantNo = split[2];
            Merchant byId = merchantService.getById(merchantNo);
            if (byId == null) {
                throw new BusinessException("商户不存在！");
            }
            if (byId.getSubMchId() == null) {
                throw new BusinessException("商户配置子商户id不存在！");
            }
            if (!businessCoupon.getBelongMerchant().equals(byId.getSubMchId())) {
                throw new BusinessException("核销商家券不在当前登录商户下！");
            }
        }


        if (memberCoupon == null) {
            throw new BusinessException("该商家券码不存在！");
        }
        JSONObject paramsObject = new JSONObject();
        paramsObject.put("coupon_code", couponCode);
        paramsObject.put("stock_id", memberCoupon.getStockId());
        paramsObject.put("appid", serviceBusiness.getAppId());
        paramsObject.put("use_time", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
                .format(new Date()));
        paramsObject.put("use_request_no", outRequestNo);
        paramsObject.put("openid", memberCoupon.getPayOpenid());

        String reqdata = JSON.toJSONString(paramsObject);


        log.info("核销商家券请求参数：" + reqdata);
        HttpPost httpPost = new HttpPost(useCouponUrl);
        InputStream stream = new ByteArrayInputStream(reqdata.getBytes("utf-8"));
        InputStreamEntity reqEntity = new InputStreamEntity(stream);
        reqEntity.setContentType("application/json");
        httpPost.setEntity(reqEntity);
        httpPost.addHeader("Accept", "application/json");
        CloseableHttpResponse response = httpClient.execute(httpPost);
        String result = HttpUtil.handleResponse("url", "UTF-8", response);
        if (result != null) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            if (jsonObject == null) {
                throw new BusinessException(result);
            }
            String wechatpay_use_time = jsonObject.getString("wechatpay_use_time");
            if (wechatpay_use_time == null || StringUtils.isBlank(wechatpay_use_time)) {
                throw new BusinessException(result);
            }
        } else {
            throw new BusinessException("核销商家券异常");
        }

        MemberCoupon params = new MemberCoupon();
        params.setId(memberCoupon.getId());
        params.setState(1);
        memberCouponService.updateById(params);

        /*将订单中商家券的发放状态改为1*/
        TOrder order = orderService.selectByOutTradeNo(memberCoupon.getOutTradeNo());
        TOrder tOrder = new TOrder();
        tOrder.setId(order.getId());
        tOrder.setSendType(2);
        orderService.updateById(tOrder);
    }

    @Override
    public int updateState(BusinessCoupon businessCoupon) {
        int i = businessCouponMapper.updateById(businessCoupon);
        return i;
    }

    @Override
    public List<BusinessCoupon> selectAll(BusinessCoupon businessCoupon) {
        QueryWrapper<BusinessCoupon> queryWrapper = new QueryWrapper<>();
        if (businessCoupon.getHType() != null) {
            queryWrapper.eq("h_type", businessCoupon.getHType());
        }
        List<BusinessCoupon> businessCoupons = businessCouponMapper.selectList(queryWrapper);
        return businessCoupons;
    }
}
